package core.android.tools;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class AKBitmapUtil {
    private static String TAG = AKBitmapUtil.class.getName();

    /**
     * 仿微信群组头像配置文件位置
     */
    private static final String WX_PROPERTIES_1 = "1.0,1.0,198.0,198.0;";
    private static final String WX_PROPERTIES_2 = "1.0,51.0,98.0,98.0;101.0,51.0,98.0,98.0;";
    private static final String WX_PROPERTIES_3 = "51.0,1.0,98.0,98.0;1.0,101.0,98.0,98.0;101.0,101.0,98.0,98.0;";
    private static final String WX_PROPERTIES_4 = "1.0,1.0,98.0,98.0;101.0,1.0,98.0,98.0;1.0,101.0,98.0,98.0;101.0,101.0,98.0,98.0;";
    private static final String WX_PROPERTIES_5 = "34.333332,34.333336,64.666664,64.666664;101.0,34.333336,64.666664,64.666664;1.0,101.0,64.666664,64.666664;67.666664,101.0,64.666664,64.666664;134.33333,101.0,64.666664,64.666664;";
    private static final String WX_PROPERTIES_6 = "1.0,34.333336,64.666664,64.666664;67.666664,34.333336,64.666664,64.666664;134.33333,34.333336,64.666664,64.666664;1.0,101.0,64.666664,64.666664;67.666664,101.0,64.666664,64.666664;134.33333,101.0,64.666664,64.666664;";
    private static final String WX_PROPERTIES_7 = "67.666664,1.0,64.666664,64.666664;1.0,67.666664,64.666664,64.666664;67.666664,67.666664,64.666664,64.666664;134.33333,67.666664,64.666664,64.666664;1.0,134.33333,64.666664,64.666664;67.666664,134.33333,64.666664,64.666664;134.33333,134.33333,64.666664,64.666664;";
    private static final String WX_PROPERTIES_8 = "34.333332,1.0,64.666664,64.666664;101.0,1.0,64.666664,64.666664;1.0,67.666664,64.666664,64.666664;67.666664,67.666664,64.666664,64.666664;134.33333,67.666664,64.666664,64.666664;1.0,134.33333,64.666664,64.666664;67.666664,134.33333,64.666664,64.666664;134.33333,134.33333,64.666664,64.666664;";
    private static final String WX_PROPERTIES_9 = "1.0,1.0,64.666664,64.666664;67.666664,1.0,64.666664,64.666664;134.33333,1.0,64.666664,64.666664;1.0,67.666664,64.666664,64.666664;67.666664,67.666664,64.666664,64.666664;134.33333,67.666664,64.666664,64.666664;1.0,134.33333,64.666664,64.666664;67.666664,134.33333,64.666664,64.666664;134.33333,134.33333,64.666664,64.666664;";


    /**
     * 传入要合成的bitmap的数量
     *
     * @param BipmapCount
     * @return
     */
    public static String getWxPropertieCount(int BipmapCount) {
        switch (BipmapCount) {
            case 1:
                return WX_PROPERTIES_1;
            case 2:
                return WX_PROPERTIES_2;
            case 3:
                return WX_PROPERTIES_3;
            case 4:
                return WX_PROPERTIES_4;
            case 5:
                return WX_PROPERTIES_5;
            case 6:
                return WX_PROPERTIES_6;
            case 7:
                return WX_PROPERTIES_7;
            case 8:
                return WX_PROPERTIES_8;
            case 9:
                return WX_PROPERTIES_9;
            default:
                return WX_PROPERTIES_1;
        }
    }

    static public Drawable getScaleDraw(String imgPath, Context mContext) {

        Bitmap bitmap = null;
        try {
            Log.d(TAG, "[getScaleDraw]imgPath is " + imgPath.toString());
            File imageFile = new File(imgPath);
            if (!imageFile.exists()) {
                Log.d(TAG, "[getScaleDraw]file not  exists");
                return null;
            }
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imgPath, opts);

            opts.inSampleSize = computeSampleSize(opts, -1, 800 * 480);
            // Log.d(TAG,"inSampleSize===>"+opts.inSampleSize);
            opts.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeFile(imgPath, opts);

        } catch (OutOfMemoryError err) {
            Log.d(TAG, "[getScaleDraw] out of memory");

        }
        if (bitmap == null) {
            return null;
        }
        Drawable resizeDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
        return resizeDrawable;
    }

    /**
     * 保存bitmap到本地
     *
     * @param bitmap
     * @return
     * @throws FileNotFoundException
     */
    public static String saveBitmapJPG(Bitmap bitmap) throws FileNotFoundException {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File imgFile = new File(AKPathUtil.getInstance().getImageDir().getPath(), "IMG_" + timeStamp + ".jpg");
        BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(imgFile));
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
        return imgFile.getAbsolutePath();
    }


    public static int computeSampleSize(BitmapFactory.Options options,
                                        int minSideLength, int maxNumOfPixels) {

        int initialSize = computeInitialSampleSize(options, minSideLength,
                maxNumOfPixels);
        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }

        return roundedSize;

    }

    private static int computeInitialSampleSize(BitmapFactory.Options options,
                                                int minSideLength, int maxNumOfPixels) {

        double w = options.outWidth;
        double h = options.outHeight;
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
                .sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
                Math.floor(w / minSideLength), Math.floor(h / minSideLength));

        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }

        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }

    }

    public static Bitmap drawableToBitmap(Drawable drawable) {

        Bitmap bitmap = Bitmap
                .createBitmap(
                        drawable.getIntrinsicWidth(),
                        drawable.getIntrinsicHeight(),
                        drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
                                : Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        canvas.setBitmap(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    public static Bitmap decodeBitmap(Resources res, int id) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeResource(res, id, options);
        if (bitmap == null) {
            AK.d("bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        AK.d("真实图片高度：" + realHeight + "宽度:" + realWidth);
        // 计算缩放比
        int scale = (int) ((realHeight > realWidth ? realHeight : realWidth) / 100);
        if (scale <= 0) {
            scale = 1;
        }
        AK.d("scale=>" + scale);
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。
        bitmap = BitmapFactory.decodeResource(res, id, options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        AK.d("缩略图高度：" + h + "宽度:" + w);
        return bitmap;
    }


    /**
     * 将多个Bitmap合并成一个图片。
     *
     * @param columns 将多个图合成多少列
     * @param bitmaps ... 要合成的图片
     * @return
     */
    public static Bitmap combineBitmaps(int columns, Bitmap... bitmaps) {
        if (columns <= 0 || bitmaps == null || bitmaps.length == 0) {
            throw new IllegalArgumentException(
                    "Wrong parameters: columns must > 0 and bitmaps.length must > 0.");
        }
        int maxWidthPerImage = 20;
        int maxHeightPerImage = 20;
        for (Bitmap b : bitmaps) {
            maxWidthPerImage = maxWidthPerImage > b.getWidth() ? maxWidthPerImage
                    : b.getWidth();
            maxHeightPerImage = maxHeightPerImage > b.getHeight() ? maxHeightPerImage
                    : b.getHeight();
        }
        AK.d("maxWidthPerImage=>" + maxWidthPerImage
                + ";maxHeightPerImage=>" + maxHeightPerImage);
        int rows = 0;
        if (columns >= bitmaps.length) {
            rows = 1;
            columns = bitmaps.length;
        } else {
            rows = bitmaps.length % columns == 0 ? bitmaps.length / columns
                    : bitmaps.length / columns + 1;
        }
        Bitmap newBitmap = Bitmap.createBitmap(columns * maxWidthPerImage, rows
                * maxHeightPerImage, Config.ARGB_8888);
        AK.d("newBitmap=>" + newBitmap.getWidth() + ","
                + newBitmap.getHeight());
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < columns; y++) {
                int index = x * columns + y;
                if (index >= bitmaps.length)
                    break;
                AK.d("y=>" + y + " * maxWidthPerImage=>"
                        + maxWidthPerImage + " = " + (y * maxWidthPerImage));
                AK.d("x=>" + x + " * maxHeightPerImage=>"
                        + maxHeightPerImage + " = " + (x * maxHeightPerImage));
                newBitmap = mixtureBitmap(newBitmap, bitmaps[index],
                        new PointF(y * maxWidthPerImage, x * maxHeightPerImage));
            }
        }
        return newBitmap;
    }

    /**
     * Mix two Bitmap as one.
     *
     * @param first
     * @param second
     * @param fromPoint where the second bitmap is painted.
     * @return
     */
    public static Bitmap mixtureBitmap(Bitmap first, Bitmap second, PointF fromPoint) {
        if (first == null || second == null || fromPoint == null) {
            return null;
        }
        Bitmap newBitmap = Bitmap.createBitmap(first.getWidth(), first.getHeight(), Config.RGB_565);
        Canvas cv = new Canvas(newBitmap);
        cv.drawBitmap(first, 0, 0, null);
        cv.drawBitmap(second, fromPoint.x, fromPoint.y, null);
        cv.save(Canvas.ALL_SAVE_FLAG);
        cv.restore();
        return newBitmap;
    }

    public static void getScreenWidthAndHeight(Activity mContext) {
        DisplayMetrics metric = new DisplayMetrics();
        mContext.getWindowManager().getDefaultDisplay().getMetrics(metric);
        int width = metric.widthPixels; // 屏幕宽度（像素）
        int height = metric.heightPixels; // 屏幕高度（像素）
        AK.d("screen width=>" + width + ",height=>" + height);
    }

    /**
     * /** 传入新的宽高，计算缩放比 options.inSampleSize = reckonThumbnail(options.outWidth,
     * options.outHeight, newWidth, newHeight);
     *
     * @param oldWidth
     * @param oldHeight
     * @param newWidth
     * @param newHeight
     * @return 返回int的新的缩放比
     */
    public static int reckonThumbnail(int oldWidth, int oldHeight, int newWidth, int newHeight) {
        if ((oldHeight > newHeight && oldWidth > newWidth) || (oldHeight <= newHeight && oldWidth > newWidth)) {
            int be = (int) (oldWidth / (float) newWidth);
            if (be <= 1)
                be = 1;
            return be;
        } else if (oldHeight > newHeight && oldWidth <= newWidth) {
            int be = (int) (oldHeight / (float) newHeight);
            if (be <= 1)
                be = 1;
            return be;
        }
        return 1;
    }

    /**
     * 处理图片
     *
     * @param bm        所要转换的bitmap
     * @param newWidth  新的宽
     * @param newHeight 新的高
     * @return 指定宽高的bitmap
     */
    public static Bitmap zoomImg(Bitmap bm, int newWidth, int newHeight) {
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
        return newbm;
    }

    /**
     * 转换View到Bitmap 会导致view发送移动-不推荐
     */
    @Deprecated
    public static Bitmap getBitmapFromView(View view) {
        Bitmap bitmap = null;
        int width = view.getWidth();
        int height = view.getHeight();
        if (width != 0 && height != 0) {
            bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            view.layout(0, 0, width, height);
            view.draw(canvas);
        }
        return bitmap;
    }

    /**
     * 转换View到Bitmap2 不会导致view发送移动
     */
    public static Bitmap getBitmapFromView2(View view) {
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
        view.setDrawingCacheEnabled(false);
        return bmp;
    }

    /**
     * 把bitmap压缩并转换成文件(上传必用)
     * Android压缩图片到100K以下并保持不失真的高效方法
     */
    public static File getUploadSmall(String filePath) throws FileNotFoundException {
        File orignPic = new File(filePath);
        File imgFile = new File(AKPathUtil.getInstance().getTempDir(), orignPic.getName());
        if (orignPic.exists()) {
            Bitmap bm = getSmallBitmap(filePath);
            BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(imgFile));
            bm.compress(Bitmap.CompressFormat.JPEG, 40, os);
        }
        return imgFile;
    }

    /**
     * 计算图片的缩放值
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee
            // a final image with both dimensions larger than or equal to the
            // requested height and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }


    /**
     * 根据路径获得图片并压缩返回bitmap用于显示
     */
    public static Bitmap getSmallBitmap(String filePath) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, 480, 800);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }


    /**
     * 保存bitmap到相册并广播更新
     *
     * @param context
     * @param bmp
     */
    public static File saveBitmapToGallery(Context context, Bitmap bmp) {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        // 首先保存图片
        File imgFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "IMG_" + timeStamp + ".jpg");
        AK.d(imgFile);
        try {
            FileOutputStream fos = new FileOutputStream(imgFile);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        // 其次把文件插入到系统图库
        try {
            MediaStore.Images.Media.insertImage(context.getContentResolver(), imgFile.getAbsolutePath(), imgFile.getName(), null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 最后通知图库更新
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imgFile)));
        return imgFile;
    }

    /**
     * 压缩图片直到容量小于指定值(kb)，并保存到sdcard
     * 例子压缩图片直到容量小于200kb:
     * saveBitmap2SDWithCapacity(relativePath, fileName, bm, 200)
     */
    public static int saveBitmap2SDWithCapacity(String relativePath, String fileName, Bitmap bm, int capacity) {
        if (!relativePath.endsWith("/")) {
            relativePath = relativePath + "/";
        }
        FileOutputStream out = null;
        ByteArrayInputStream bais = null;
        try {
            File file = new File(AKPathUtil.getInstance().getFileDir(), fileName);
            file.createNewFile();
            out = new FileOutputStream(file.getPath());
//            bm.compress(Bitmap.CompressFormat.JPEG, 90, out);
            bais = compressImage(bm, capacity);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = bais.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        } finally {
            AKIOUtil.closeIO(out, bais);
        }
    }


    /**
     * 压缩图片直到容量小于指定值(kb)
     *
     * @param image
     * @param capacity
     * @return
     */
    public static ByteArrayInputStream compressImage(Bitmap image, int capacity) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > capacity) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%，把压缩后的数据存放到baos中
            if (options < 10) {
                break;
            }
            options -= 10;//每次都减少10
        }
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        baos.reset();
        return bais;
    }

    public static Bitmap getBitmapFromUrl(String url) {
        Bitmap bitmap = null;
        try {
            URLConnection conn = new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(10000);
            bitmap = BitmapFactory.decodeStream((InputStream) conn.getContent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

}